package com.example.selenium;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.selenium.mapper.WaybillMapper;
import com.example.selenium.service.AsyncService;
import com.example.selenium.util.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@SpringBootApplication
@MapperScan(basePackages = {"com.example.selenium.mapper"})
@EnableAsync
public class AutomaticGrabForTrackId {
    protected static Logger logger = LoggerFactory.getLogger(AutomaticGrabForTrackId.class);

    public static String redisLPushKey="y2t:trackIds";

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private AsyncService asyncService;

    @Autowired
    private WaybillMapper waybillMapper;



    private static final String LOGIN_NAME = "13926676253";
    private static final String LOGIN_PWD = "ZDwl1234*";
    private static final String LOGIN_URL = "https://apit.y2t.com/cockpit-lhk/login";
    private static final String RUN_PATH = "C:\\chromedriver_win32\\chromedriver.exe";
    private static Map<Integer,String> companyMap = new HashMap<>();


    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(AutomaticGrabForTrackId.class, args);
        AutomaticGrabForTrackId automaticGrab = applicationContext.getBean(AutomaticGrabForTrackId.class);



        // 获取运单详情
//        automaticGrab.loginProcessor();
//        String cookieV = automaticGrab.getCookie();
//        for (int i = 0; i < 7; i++) {
//            automaticGrab.asyncRequest(cookieV);
//        }

    }

    public void testLPush(){
        redisUtil.lpush("yyyttt","L202007010002390620","L202109181520460237");

    }

    /**
     * 异步请求运易通
     * @param cookieV
     */
    public void asyncRequest(String cookieV){
        asyncService.requestY2T(cookieV);
    }


    /**
     * 获取driver
     * @return
     */
    public static WebDriver getDriver(){
        ChromeOptions options = new ChromeOptions();
        System.setProperty("webdriver.chrome.driver", RUN_PATH);
        options.setExperimentalOption("excludeSwitches", Arrays.asList("enable-automation"));
        WebDriver driver = new ChromeDriver(options);
        driver.manage().window().setSize(new Dimension(1360, 850));
        return driver;
    }

    /**
     * 自动登录
     * @throws InterruptedException
     */
    private static void autoLogin(WebDriver driver) throws InterruptedException {
        // http://merchant.yxtweb.com/index.html
        // String jsStr = "window.alert(\"请尽快完成验证码和用户名的输入！\")";
        // ((JavascriptExecutor) driver).executeScript(jsStr);
        boolean isNext = true;

        do {
            driver.get(LOGIN_URL);
            Thread.sleep(1000*5);

            WebElement isAlive = driver.findElement(By.xpath("//*[@id=\"userName\"]"));
            if (null == isAlive) {
                 Thread.sleep(1000*30);
                 continue;
            }

            sendkeys(LOGIN_NAME, driver.findElement(By.xpath("//*[@id=\"userName\"]")));

            sendkeys(LOGIN_PWD, driver.findElement(By.xpath("//*[@id=\"passWord\"]")));
            Thread.sleep(1000 * 5);
            logger.info("请输入用户名验证码！");
            // 截图验证码
            WebElement checkCodeE = driver.findElement(By.xpath("//*[@id=\"checkCode\"]"));
            File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            String vcodeimgPath = "C:\\verifyCode\\test.png";
            try {
                FileUtils.copyFile(captureElement(src, checkCodeE), new File(vcodeimgPath));
            } catch (IOException e) {
                e.printStackTrace();
            }

            System.err.println("------------------------------------------------------------------------------------");

            // 这里开始识别验证码
            String vCodeResult = OcrUtils.imgOcr(vcodeimgPath).replaceAll(" ", "").replaceAll("\n", "");
            System.err.println("vCodeResult=" + vCodeResult);
            String inputVCodeJs = "document.getElementById(\"verFiCode\").value='" + vCodeResult + "';";
            System.err.println("inputVCodeJs=" + inputVCodeJs);
            ((JavascriptExecutor) driver).executeScript(inputVCodeJs);
            // driver.findElement(By.xpath("//*[@id=\"verFiCode\"]")).sendKeys(vCodeResult.replaceAll("
            // ", ""));

            Thread.sleep(1000 * 5);

            driver.findElement(By.xpath("//*[@id=\"login\"]")).click();
            Thread.sleep(1000 * 3);

            // 错误messges如果出现表明需要进入下一次登录，因为错误了
            WebElement showMassage = driver.findElement(By.xpath("//*[@id=\"showMassage\"]"));
            if (null != showMassage && showMassage.isDisplayed()) {
                isNext = true;
            } else {
                isNext = false;
                WebElement isOnLine = driver.findElement(By.xpath("//*[@id=\"kickedNo\"]"));
                if (null != isOnLine && isOnLine.isDisplayed() && isOnLine.isEnabled()) {
                    isOnLine.click();
                }
            }
        } while (isNext);
        logger.info("成功登录运易通，如果有出现同时在线的情况，需要特殊处理，请尽快完成处理!");
    }

    /**
     * 获取cookie
     * @param webDriver
     */
    public  void setLoginCookie(WebDriver webDriver){
        String jsessionIdCookie = "";
        String sinoSSOCookie = "";
        Set<Cookie> cookies = webDriver.manage().getCookies();

        Iterator<Cookie> iterator = cookies.iterator();
        while (iterator.hasNext()){
            Cookie next = iterator.next();
            if(next.getName().equalsIgnoreCase("JSESSIONID")){
                jsessionIdCookie =next.getValue();
                continue;
            }
            if(next.getName().equalsIgnoreCase("SinoSSO")){
                sinoSSOCookie =next.getValue();
                continue;
            }
        }
        redisUtil.set("y2tLoginCookie","JSESSIONID="+jsessionIdCookie+"; SinoSSO="+sinoSSOCookie);
    }



    /**
     * 根据公司名字获取id
     * @param
     * @return
     */
    private  Integer getCompany(){
        String url = "https://apit.y2t.com/lhk/proxy/sysconfig/PublicInterface/findSysCompanyAll?_="+new Date().getTime();
        String response = HttpClientUtil.doGet(url, null, getCookie());
        try{
            if(StringUtils.isNotEmpty(response)){
                JSONObject jsonObject = JSONObject.parseObject(response);
                if("true".equals(jsonObject.getString("status"))){
                    JSONArray array = jsonObject.getJSONArray("data");
                    if(CollectionUtils.isNotEmpty(array)){
                        companyMap.clear();
                        for (int i = 0; i < array.size(); i++) {
                            JSONObject data = (JSONObject) array.get(i);
                            Integer companyId = data.getInteger("id");
                            String companyName = data.getString("name");
                            companyMap.put(companyId,companyName);
                        }
                    }
                }
            }
        }catch (Exception e){
            return -1;
        }
        return 0;
    }


    /**
     * 登录后置处理
     * @throws InterruptedException
     */
    public void loginProcessor() throws InterruptedException {
        String cookie = getCookie();
        // 预请求，验证cookie是否还有效
        if(StringUtils.isNotEmpty(cookie)){
            Integer status = getCompany();
            if(status==0){
                return;
            }
        }
        WebDriver driver = getDriver();
        autoLogin(driver);
        setLoginCookie(driver);
        System.out.println("get完毕");
    }




    /**
     * 获取cookie
     * @return
     */
    public String getCookie(){
        Object obj = redisUtil.get("y2tLoginCookie");
        if(obj==null){
            return "";
        }else{
            return (String)obj;
        }
    }

    public static void sendkeys(String sts, WebElement we) throws InterruptedException {
        char[] s = sts.toCharArray();
        for (char ss : s) {
            we.sendKeys(String.valueOf(ss));
            Thread.sleep(200);
        }
    }


    /**
     *
     * @param screenshot
     * @param element
     * @return
     */
    public static File captureElement(File screenshot, WebElement element){
        try {
            BufferedImage img = ImageIO.read(screenshot);
            int width = element.getSize().getWidth();
            int height = element.getSize().getHeight();
            //获取指定元素的坐标
            Point point = element.getLocation();
            //从元素左上角坐标开始，按照元素的高宽对img进行裁剪为符合需要的图片
            BufferedImage dest = img.getSubimage(point.getX(), point.getY(), width, height);
            ImageIO.write(dest, "png", screenshot);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return screenshot;
    }



    /**
     * lpush
     */
    public void lPush(){
        String trackId = "L0";
        while (true){
            List<String> list = waybillMapper.tempSelectAllTrackId(trackId);
            if(CollectionUtils.isNotEmpty(list)){
                for (int i = 0; i < list.size(); i++) {
                    System.out.println("-------------正在添加trackId= "+trackId);
                    redisUtil.lpush(redisLPushKey,list.get(i));
                    trackId = list.get(i);
                }
            }else{
                System.out.println("-------------------添加完毕----------------------------");
                return;
            }
        }
    }
}
